import React, { useEffect, useMemo, useRef, useState } from "react";
import { Button, Tree, Space, Modal, message, Input } from 'antd'; 
import { DataNode } from "antd/es/tree";
import { menuTypes, functionTypes } from "@/constants/types";
import { ProTable } from "@ant-design/pro-components";
import { FUNCTION_LEVEL } from "@/constants";
import { fetchMenuTree, fetchMenuList, fetchFunctionList, addMenu, updateMenu, deleteMenu, addFunction, updateFunction, deleteFunction } from '../services';
import '../index.less';
import { isEmptyObj } from "@/utils/util";
import MenuUpdateModal from "../modals/MenuUpdateModal";
import MenuBtnUpdateModal from "../modals/MenuBtnUpdateModal";
import { useRequest } from "ahooks";

const isFunctionLevel = (node: {level: number | undefined}) => node?.level === FUNCTION_LEVEL;


const LeftTree = ({ onSelect, refreshTree }: {onSelect: any, refreshTree: any}) => {
  const [treeData, setTreeData] = useState<DataNode []>([]);
  const [expandedKeys, setExpandedKeys] = useState<string []>([]);
  const [selectRow, setSelectRow] = useState<DataNode | null>(null);
  const [searchValue, setSearchValue] = useState<string>('');

  const onExpand = (keys: string []) => {
    setExpandedKeys(keys);
  }

  const fetchMenuTreeApi = async () => {
    const res = await fetchMenuTree();
    if (res?.code === '0' && res?.data?.length > 0) { 
      // 所有展开的节点
      const expandedList: string [] = [];
      const mapTree = (arr: any []) => {
        arr.forEach(element => {
          expandedList.push(element.id);
          if (element?.children?.length > 0) {
            mapTree(element?.children);
          }
        });
      }
      // 递归枚举树节点
      mapTree(res?.data);
      setTreeData(res?.data);
      setExpandedKeys(expandedList);
      setSelectRow(res?.data?.[0]);
      onSelect(res?.data?.[0]);
    }
  }

  useEffect(() => {
    fetchMenuTreeApi();
  }, [refreshTree])
  

  const resultTree = useMemo(() => {
    const loop = (data) =>
      data.map((item) => {
        const strTitle = item.name;
        const index = strTitle.indexOf(searchValue);
        const beforeStr = strTitle.substring(0, index);
        const afterStr = strTitle.slice(index + searchValue.length);
        const title =
          index > -1 ? (
            <span>
              {beforeStr}
              <span className="site-tree-search-value">{searchValue}</span>
              {afterStr}
            </span>
          ) : (
            <span>{strTitle}</span>
          );
        if (item.children) {
          return {
            name: title,
            id: item.id,
            children: loop(item.children),
          };
        }
        return {
          name: title,
          id: item.id,
        };
      });
    return searchValue?.trim() ? loop(treeData) : treeData;
  }, [searchValue, JSON.stringify(treeData)]);


  return (
    <div className="tree-wrapper">
      <div className="tree-search">
        <Input.Search className="search-input" onChange={e => setSearchValue(e.target.value)} />
      </div>
      <Tree
        expandedKeys={expandedKeys}
        selectedKeys={selectRow ? [selectRow?.id] : []}
        onSelect={(selected, {node}) => {
          setSelectRow(node);
          onSelect(node)
        }} 
        treeData={resultTree}
        onExpand={onExpand}
        fieldNames={{
          title: "name",
          key: "id",
          children: "children"
        }}
      />
    </div>
  );
}

const RightMenuTable = ({ node, onRefreshTree }: {node: menuTypes, onRefreshTree: any}) => {
  const tableRef = useRef();
  const [currentRow, setCurrentRow] = useState(null);
  const [visible, setVisible] = useState(false);
  const {loading: addLoading, runAsync: addApi} = useRequest(addMenu, {manual: true});
  const {loading: updateLoading, runAsync: updateApi} = useRequest(updateMenu, {manual: true});


  const contentProps = {
    title: currentRow ? '编辑菜单' : '新增菜单',
    visible,
    currentRow,
    loading: currentRow ? updateLoading : addLoading,
    onCancel: () => {
      setVisible(false);
      setCurrentRow(null);
    },
    onSubmit: async (params: any) => {
      const apiFunc = currentRow ? updateApi : addApi;
      const res = await apiFunc(currentRow ? {
        ...params, 
        id: currentRow?.id,
        level: node.level + 1,
        parentId: node?.id
      } : {
        ...params,
        level: node.level + 1,
        parentId: node?.id
      });
      if (res.code === '0') {
        message.success('操作成功');
        setVisible(false);
        setCurrentRow(null);
        tableRef?.current?.reload();
        onRefreshTree();
      }
    },
  }


  const handleAdd = () => {
    setVisible(true);
  }
  const handleDelete = (record) => {
    Modal.confirm({
      title: '是否删除此条数据',
      onOk: () => {
        deleteMenu({id: record.id}).then(() => {
          setVisible(false);
          setCurrentRow(null);
          tableRef?.current?.reload();
          onRefreshTree();
        })
      }
    });
  }
  const handleEdit = (record) => {
    setCurrentRow(record);
    setVisible(true);
  }


  const columns = [
    {
      title: '序号',
      dataIndex: 'index',
      render: (_: any, record: menuTypes, index: number) => <span>{ String(index + 1)}</span>
    },
    { 
      title: '菜单中文名称',
      dataIndex: 'name',
    },
    { 
      title: 'Code',
      dataIndex: 'functionCode',
    },
    { 
      title: '链接地址',
      dataIndex: 'path',
    },
    { 
      title: '排序',
      dataIndex: 'sort',
    },
    { 
      title: '创建时间',
      dataIndex: 'createTime',
    },
    { 
      title: '创建人',
      dataIndex: 'createBy',
    },
    { 
      title: '操作',
      dataIndex: 'options',
      width: 200,
      render: (_, record: menuTypes) => {
        return (
          <Space>
            <Button type="link" onClick={() => handleDelete(record)}>删除</Button>
            <Button type="link" onClick={() => handleEdit(record)}>编辑</Button>
          </Space>
        );
      }
    },
  ];
  
  useEffect(() => {
    if (!isEmptyObj(node)) {
      tableRef?.current?.reload();
    }
  }, [JSON.stringify(node)]);

  return (
    <>
      <div className="table-wrapper">
        <ProTable
          bordered
          actionRef={tableRef}
          search={false}
          rowKey="id"
          className="xl-no-search-protable"
          columns={columns}
          options={false}
          headerTitle={
            <Button type="primary" onClick={handleAdd}>新建子菜单</Button>
          }
          request={async () => {
            const res = await fetchMenuList({parentId: node?.id});
            return {
              data: res || [],
              success: true,
              total: res?.length || 0
            }
          }}
        />        
      </div>
      {visible && <MenuUpdateModal {...contentProps} />}
    </>
  );
}
const RightFunctionTable = ({ node }: {node: functionTypes}) => {
  const tableRef = useRef();
  const [currentRow, setCurrentRow] = useState<functionTypes | null>(null);
  const [visible, setVisible] = useState(false);
  const {loading: addLoading, runAsync: addApi} = useRequest(addFunction, {manual: true});
  const {loading: updateLoading, runAsync: updateApi} = useRequest(updateFunction, {manual: true});


  const contentProps = {
    title: currentRow ? '编辑功能' : '新增功能',
    loading: currentRow ? updateLoading : addLoading,
    visible,
    currentRow,
    onCancel: () => {
      setVisible(false);
      setCurrentRow(null);
    },
    onSubmit: async (params: functionTypes) => {
      const apiFunc = currentRow ? updateApi : addApi;
      const res = await apiFunc(currentRow ? {
        ...params, 
        id: currentRow?.id,
        pageId: node?.id
      } : {
        ...params,
        pageId: node?.id
      });
      if (res.code === '0') {
        message.success('操作成功');
        setVisible(false);
        setCurrentRow(null);
        tableRef?.current?.reload();
      }
    },
  }


  const handleAdd = () => {
    setVisible(true);
  }
  const handleDelete = (record) => {
    Modal.confirm({
      title: '是否删除此条数据',
      onOk: () => {
        deleteFunction({id: record.id}).then(res => {
          setVisible(false);
          setCurrentRow(null);
          tableRef?.current?.reload();
        })
      }
    });
  }
  const handleEdit = (record) => {
    setCurrentRow(record);
    setVisible(true);
  }
  

  
  const columns = [
    {
      title: '序号',
      dataIndex: 'index',
      render: (_: any, record: menuTypes, index: number) => <span>{ String(index + 1)}</span>
    },
    { 
      title: '按钮中文名称',
      dataIndex: 'name',
    },
    { 
      title: 'Code',
      dataIndex: 'code',
    },
    { 
      title: '创建时间',
      dataIndex: 'createTime',
    },
    { 
      title: '创建人',
      dataIndex: 'createBy',
    },
    { 
      title: '操作',
      dataIndex: 'options',
      width: 200,
      render: (_, record: menuTypes) => {
        return (
          <Space>
            <Button type="link" onClick={() => handleDelete(record)}>删除</Button>
            <Button type="link" onClick={() => handleEdit(record)}>编辑</Button>
          </Space>
        );
      }
    },
  ];

  useEffect(() => {
    if (!isEmptyObj(node)) {
      tableRef?.current?.reload();
    }
  }, [JSON.stringify(node)]);

  return (
    <>
      <div className="table-wrapper">
        <ProTable
          bordered
          actionRef={tableRef}
          search={false}
          rowKey="id"
          className="xl-no-search-protable"
          columns={columns}
          options={false}
          headerTitle={
            <Button type="primary" onClick={handleAdd}>新增功能</Button>
          }
          request={async () => {
            const res = await fetchFunctionList({pageId: node?.id});
            return {
              data: res || [],
              success: true,
              total: res?.length || 0
            }
          }}
        />
      </div>
      {visible && <MenuBtnUpdateModal {...contentProps} />}
    </>
  );
}

const MenuManage = () => {
  const [node, setNode] = useState<menuTypes | functionTypes | null>(null);
  const [refreshTree, setRefreshTree] = useState(new Date().getTime());
  const isFunction = isFunctionLevel(node);

  const onSelect = (node: DataNode) => {
    setNode(node);
  }

  const onRefreshTree = () => {
    setRefreshTree(new Date().getTime());
  }
  return (
    <>
      <div className="column-wrapper">
        <LeftTree 
          onSelect={onSelect}
          refreshTree={refreshTree}
        />
        {
          isFunction ? (
            <RightFunctionTable
              node={node}
            />
          ) : (
            <RightMenuTable
              onRefreshTree={onRefreshTree}
              node={node}
            />
          )
        }
      </div>
    </>
  );
}
export default MenuManage;